use crate::config::InterpreterConfig;
use crate::token::{Token, TokenType};
use std::collections::HashMap;

pub struct Lexer {
    input: Vec<char>,
    position: usize,
    line: usize,
    column: usize,
    config: InterpreterConfig,
}

impl Lexer {
    pub fn new(input: &str) -> Self {
        Lexer {
            input: input.chars().collect(),
            position: 0,
            line: 1,
            column: 1,
            config: InterpreterConfig::default(),
        }
    }

    pub fn new_with_config(input: &str, config: InterpreterConfig) -> Self {
        Lexer {
            input: input.chars().collect(),
            position: 0,
            line: 1,
            column: 1,
            config,
        }
    }

    pub fn tokenize(&mut self) -> Result<Vec<Token>, String> {
        let mut tokens = Vec::new();

        while !self.is_at_end() {
            self.skip_whitespace();
            if self.is_at_end() {
                break;
            }

            // 跳过注释
            if self.current() == '注' && self.peek() == Some('：') {
                self.skip_comment();
                continue;
            }

            let token = self.next_token()?;
            if token.token_type != TokenType::Newline {
                tokens.push(token);
            }
        }

        tokens.push(Token::new(TokenType::EOF, self.line, self.column));
        Ok(tokens)
    }

    fn next_token(&mut self) -> Result<Token, String> {
        let line = self.line;
        let column = self.column;
        let ch = self.current();

        let token_type = match ch {
            '、' | '，' => {
                self.advance();
                TokenType::Comma
            }
            '。' => {
                self.advance();
                TokenType::Period
            }
            '：' => {
                self.advance();
                TokenType::Colon
            }
            ':' => {
                self.advance();
                TokenType::Colon
            }
            '（' => {
                self.advance();
                TokenType::LeftParen
            }
            '(' => {
                self.advance();
                TokenType::LeftParen
            }
            '）' => {
                self.advance();
                TokenType::RightParen
            }
            ')' => {
                self.advance();
                TokenType::RightParen
            }
            '【' => {
                self.advance();
                TokenType::LeftBracket
            }
            '】' => {
                self.advance();
                TokenType::RightBracket
            }
            '」' => {
                self.advance();
                TokenType::String("".to_string()) // 在字符串外部遇到」时返回空字符串token
            }
            '《' => {
                // 《是字典开始标记
                self.advance();
                TokenType::DictStart
            }
            '》' => {
                // 》是字典结束标记
                self.advance();
                TokenType::RightBracket
            }

            '<' => {
                self.advance();
                TokenType::Lt
            }
            '>' => {
                self.advance();
                TokenType::Gt
            }
            '≤' => {
                self.advance();
                TokenType::Le
            }
            '≥' => {
                self.advance();
                TokenType::Ge
            }
            '+' => {
                self.advance();
                TokenType::Add
            }
            '-' => {
                self.advance();
                TokenType::Sub
            }
            '*' | '×' => {
                self.advance();
                TokenType::Mul
            }
            '÷' => {
                self.advance();
                TokenType::Div
            }
            '/' => {
                self.advance();
                TokenType::FloorDiv
            }
            '！' | '!' => {
                self.advance();
                TokenType::LogicNot
            }
            '「' => self.read_string()?,
            '\n' => {
                self.advance();
                let old_line = self.line;
                self.line += 1;
                self.column = 1;
                return Ok(Token::new(TokenType::Newline, old_line, column));
            }
            _ if ch.is_ascii_digit() => self.read_number()?,
            _ if ch == '负' && self.peek().map_or(false, |c| self.is_chinese_digit_char(c)) => {
                self.advance(); // Skip '负'
                let token = self.read_chinese_number()?;
                if let TokenType::Integer(n) = token {
                    TokenType::Integer(-n)
                } else {
                    token
                }
            }
            // 只有当当前字符是中文数字，且后续字符不是标识符字符时，才解析为数字
            _ if self.is_chinese_digit() && !self.is_chinese_digit_followed_by_identifier() => {
                self.read_chinese_number()?
            }
            _ if self.is_identifier_start() => self.read_identifier_or_keyword()?,
            _ => return Err(format!("未识别的字符: '{}' at {}:{}", ch, line, column)),
        };

        Ok(Token::new(token_type, line, column))
    }

    /// 读取字符串字面量。
    /// 字符串字面量必须以「开头，以」结尾，不能单独出现「或」
    /// 字符串字面量可以包含转义字符，
    /// 转义字符包括：\n、\t、\r、\\、\"、\'、「、」、《、》，
    /// 转义字符必须紧跟在反斜杠后面, 不能单独出现，
    /// 其他字符直接添加到结果中，不进行转义
    /// 字符串字面量不能包含未转义的「或」。
    /// 字符串可以包含插值表达式，使用《》包裹。
    fn read_string(&mut self) -> Result<TokenType, String> {
        self.advance(); // 跳过 「
        let mut result = String::new();
        let mut has_interpolation = false;

        while !self.is_at_end() && self.current() != '」' {
            if self.current() == '\\' {
                self.advance(); // 跳过反斜杠
                if self.is_at_end() {
                    return Err("字符串以反斜杠结束".to_string());
                }
                // 处理转义序列
                match self.current() {
                    'n' => {
                        result.push('\n');
                    }
                    't' => {
                        result.push('\t');
                    }
                    'r' => {
                        result.push('\r');
                    }
                    '\\' => {
                        result.push('\\');
                    }
                    '"' => {
                        result.push('"');
                    }
                    '\'' => {
                        result.push('\'');
                    }
                    '「' => {
                        result.push('「');
                    }
                    '」' => {
                        result.push('」');
                    }
                    '《' => {
                        result.push('《');
                    }
                    '》' => {
                        result.push('》');
                    }
                    _ => {
                        // 对于未知转义序列，保持反斜杠和字符原样
                        result.push('\\');
                        result.push(self.current());
                    }
                }
                self.advance();
            } else if self.current() == '《' && self.config.enable_string_interpolation {
                // 遇到插值开始标记，标记为包含插值
                has_interpolation = true;

                // 将《添加到结果中，稍后由语法分析器处理
                result.push(self.current());
                self.advance();

                // 收集插值表达式内容，包括嵌套的《》
                let mut brace_count = 1; // 已经遇到了一个《

                while !self.is_at_end() && brace_count > 0 {
                    if self.current() == '《' {
                        brace_count += 1;
                    } else if self.current() == '》' {
                        brace_count -= 1;
                    }
                    result.push(self.current());
                    self.advance();
                }

                if brace_count > 0 {
                    return Err("插值表达式未闭合".to_string());
                }
            } else {
                result.push(self.current());
                self.advance();
            }
        }

        if self.is_at_end() {
            return Err("字符串未闭合".to_string());
        }

        self.advance(); // 跳过 」

        if has_interpolation {
            Ok(TokenType::StringWithInterpolation(result))
        } else {
            Ok(TokenType::String(result))
        }
    }

    fn read_number(&mut self) -> Result<TokenType, String> {
        let mut num_str = String::new();
        let mut is_float = false;

        while !self.is_at_end() && (self.current().is_ascii_digit() || self.current() == '.') {
            if self.current() == '.' {
                if is_float {
                    break;
                }
                is_float = true;
            }
            num_str.push(self.current());
            self.advance();
        }

        if is_float {
            Ok(TokenType::Float(num_str.parse().unwrap()))
        } else {
            Ok(TokenType::Integer(num_str.parse().unwrap()))
        }
    }

    fn read_chinese_number(&mut self) -> Result<TokenType, String> {
        let num_map: HashMap<char, i64> = [
            ('零', 0),
            ('一', 1),
            ('二', 2),
            ('三', 3),
            ('四', 4),
            ('五', 5),
            ('六', 6),
            ('七', 7),
            ('八', 8),
            ('九', 9),
            ('十', 10),
            ('百', 100),
            ('千', 1000),
            ('万', 10000),
        ]
        .iter()
        .cloned()
        .collect();

        let mut result = 0i64;
        let mut current_num = 0i64;
        let mut has_digit = false;

        while !self.is_at_end() && num_map.contains_key(&self.current()) {
            let ch = self.current();
            let val = num_map[&ch];

            if val < 10 {
                current_num = val;
                has_digit = true;
            } else if val == 10 {
                if current_num == 0 {
                    current_num = 1;
                }
                result += current_num * 10;
                current_num = 0;
                has_digit = false;
            } else {
                if current_num == 0 && !has_digit {
                    current_num = 1;
                }
                result += current_num * val;
                current_num = 0;
                has_digit = false;
            }

            self.advance();
        }

        result += current_num;
        Ok(TokenType::Integer(result))
    }

    fn read_identifier_or_keyword(&mut self) -> Result<TokenType, String> {
        let mut ident = String::new();

        while !self.is_at_end() && self.is_identifier_char() {
            ident.push(self.current());
            self.advance();
        }

        let token_type = match ident.as_str() {
            "篇章" => TokenType::Chapter,
            "引" => TokenType::Import,
            "引言" => TokenType::Intro,
            "正文" => TokenType::Body,
            "结语" => TokenType::Conclusion,
            "毕" => TokenType::End,
            "有" => TokenType::Have,
            "恒有" => TokenType::Const,
            "为" => TokenType::Is,
            "者" => TokenType::Thing,
            "曰" => TokenType::Say,
            "使" => TokenType::Use,
            "归" => TokenType::Return,
            "缺则" => TokenType::DefaultIf,
            "指" => TokenType::Specify,
            "于" => TokenType::At,
            "与" => TokenType::And,
            "以" => TokenType::With,
            "物之属" => TokenType::ClassOf,
            "乃" => TokenType::IsA,
            "其" => TokenType::Its,
            "父" => TokenType::Parent,
            "之" => TokenType::Of,
            "如" => TokenType::If,
            "则" => TokenType::Then,
            "否则" => TokenType::Else,

            "当" => TokenType::While,
            "之时" => TokenType::WhenTime,
            "行" => TokenType::Do,
            "直至" => TokenType::Until,
            "自" => TokenType::From,
            "至" => TokenType::To,
            "步" => TokenType::Step,
            "循环" => TokenType::Loop,
            "遍" => TokenType::ForEach,
            "止" => TokenType::Break,
            "续" => TokenType::Continue,
            "试" => TokenType::Try,
            "若有" => TokenType::Catch,
            "抛" => TokenType::Throw,
            "终" => TokenType::Finally,
            "取" => TokenType::Import,
            "示" => TokenType::Export,

            // 算术运算符
            "加" => TokenType::Add,
            "+" => TokenType::Add,
            "减" => TokenType::Sub,
            "-" => TokenType::Sub,
            "乘" => TokenType::Mul,
            "*" => TokenType::Mul,
            "×" => TokenType::Mul,
            "除" => TokenType::Div,
            "÷" => TokenType::Div,
            "整除" => TokenType::FloorDiv,
            "余" => TokenType::Mod,
            "模" => TokenType::Mod,

            // 关系运算符
            "大於" | "大于" => TokenType::Gt,
            ">" => TokenType::Gt,
            "小於" | "小于" => TokenType::Lt,
            "<" => TokenType::Lt,
            "等於" | "等于" => TokenType::Eq,
            "不等於" | "不等于" => TokenType::Ne,
            "≠" => TokenType::Ne,
            "大於等於" | "大于等于" => TokenType::Ge,
            "≥" => TokenType::Ge,
            "小於等於" | "小于等于" => TokenType::Le,
            "≤" => TokenType::Le,

            // 逻辑运算符
            "且" => TokenType::LogicAnd,
            "或" => TokenType::LogicOr,
            "非" => TokenType::LogicNot,
            "!" => TokenType::LogicNot,
            "！" => TokenType::LogicNot,

            "真" => TokenType::True,
            "伪" => TokenType::False,

            "无" => TokenType::Null,

            "集" => TokenType::List,
            "辞" => TokenType::Dict,
            "汇" => TokenType::Set,
            "组" => TokenType::Tuple,

            "书" => TokenType::Identifier("书".to_string()),
            "书行" => TokenType::Identifier("书行".to_string()),

            "置" => TokenType::SetValue,

            // 通过不将复合赋值运算符视为单个标识符来处理它们
            // 这些应被解析为单独的标记：运算符 + "为"
            "加为" => {
                // 回溯以只返回 “加”，并将 “为” 留给下一个标记
                self.position -= 1;
                self.column -= 1;
                TokenType::Add
            }
            "减为" => {
                self.position -= 1;
                self.column -= 1;
                TokenType::Sub
            }
            "乘为" => {
                self.position -= 1;
                self.column -= 1;
                TokenType::Mul
            }
            "除为" => {
                self.position -= 1;
                self.column -= 1;
                TokenType::Div
            }
            "余为" => {
                self.position -= 1;
                self.column -= 1;
                TokenType::Mod
            }
            _ => TokenType::Identifier(ident),
        };

        Ok(token_type)
    }

    fn is_chinese_digit(&self) -> bool {
        self.is_chinese_digit_char(self.current())
    }

    fn is_chinese_digit_char(&self, ch: char) -> bool {
        matches!(
            ch,
            '零' | '一'
                | '二'
                | '三'
                | '四'
                | '五'
                | '六'
                | '七'
                | '八'
                | '九'
                | '十'
                | '百'
                | '千'
                | '万'
        )
    }

    fn is_chinese_digit_followed_by_identifier(&self) -> bool {
        if !self.is_chinese_digit() {
            return false;
        }

        // 检查下一个字符是否是标识符字符（但不是中文数字）
        if let Some(next_ch) = self.peek() {
            // 如果下一个字符是标识符字符且不是中文数字，则当前中文数字应该是标识符的一部分
            self.is_identifier_char_excluding_chinese_digit(next_ch)
        } else {
            false
        }
    }

    fn is_identifier_char_excluding_chinese_digit(&self, ch: char) -> bool {
        // 不包含标点符号和中文数字
        if matches!(ch, '、' | '，' | '。' | '：' | '「' | '」' | '（' | '）') {
            return false;
        }
        if self.is_chinese_digit_char(ch) {
            return false;
        }
        ch.is_alphanumeric() || ch == '_' || (ch as u32) >= 0x4E00
    }

    fn is_identifier_start(&self) -> bool {
        let ch = self.current();
        ch.is_alphabetic() || ch == '_' || (ch as u32) >= 0x4E00
    }

    fn is_identifier_char(&self) -> bool {
        let ch = self.current();
        // 不包含标点符号
        if matches!(
            ch,
            '、' | '，' | '。' | '：' | '「' | '」' | '（' | '）' | '【' | '】'
        ) {
            return false;
        }
        // 允许《和》作为标识符的一部分
        ch.is_alphanumeric() || ch == '_' || (ch as u32) >= 0x4E00 || ch == '《' || ch == '》'
    }

    fn skip_whitespace(&mut self) {
        while !self.is_at_end() && self.current().is_whitespace() && self.current() != '\n' {
            self.advance();
        }
    }

    fn skip_comment(&mut self) {
        while !self.is_at_end() && self.current() != '\n' {
            self.advance();
        }
    }

    fn current(&self) -> char {
        self.input[self.position]
    }

    fn peek(&self) -> Option<char> {
        if self.position + 1 < self.input.len() {
            Some(self.input[self.position + 1])
        } else {
            None
        }
    }

    fn advance(&mut self) {
        if !self.is_at_end() {
            self.position += 1;
            self.column += 1;
        }
    }

    fn is_at_end(&self) -> bool {
        self.position >= self.input.len()
    }
}
